﻿module Sustainalytics.EsgRatings.Admin {

    import Common = Sustainalytics.Common;
    import CommonAdmin = Sustainalytics.Common.Admin;
    import LRTM = Sustainalytics.LRTM;
    import AdminAccounts = Sustainalytics.Accounts.Admin;

    export class WeightMatricesController {

        public selectedFile: any;
        public loading: boolean;

        public defaultWeightMatrix: WeightMatrix;
        public accountWeightMatrices: WeightMatrix[];
        public accountScheduledWeightMatrices: WeightMatrix[]; //from EsgInputFile
        public totalSlots: number;

        public selectedAccount: AdminAccounts.AccountsDto = null;
        public isEditCustomMatrix: boolean = false;

        //public uploadDetails: string;
        public weightMatrixUploadErrors: string;
        public accountsList: AdminAccounts.AccountsDto[];
        public accountId: string;

        public showAccountsDropdown: boolean = false;

        constructor(
            private $rootScope: any,
            private $scope: ng.IScope,
            private $q: ng.IQService,
            private $location: ng.ILocationService,
            private $state: ng.ui.IStateService,
            private $modal: Common.IModal,
            private WeightMatricesService : IWeightMatricesService,
            private LongRunningTaskManagerService: LRTM.LongRunningTaskManagerService,
            private notificationFactory: Common.INotificationFactory,
            private AccountsService: AdminAccounts.AccountsService)
        {

            var ctx = this;
            $scope['weightMatrices'] = this;
            ctx.getWeightMatricesByAccountId("00000000-0000-0000-0000-000000000000");
            ctx.getAccountSelectOptions();
            ctx.getMatricesSlotsPerPlatform();
        }

        public getWeightMatricesByAccountId(accountId: string): ng.IPromise<WeightMatrix[]> {
            var ctx = this;
            var promise = ctx.WeightMatricesService.listWeightMatricesByAccountId(accountId, false);
            promise.then((matrices: WeightMatrix[]) =>
            {
                if (accountId == "00000000-0000-0000-0000-000000000000")
                {
                    if (matrices.length == 1) {
                        ctx.defaultWeightMatrix = matrices[0];
                    }
                    else {
                        ctx.defaultWeightMatrix = new WeightMatrix();
                        ctx.defaultWeightMatrix.id = "00000000-0000-0000-0000-000000000000";
                        ctx.defaultWeightMatrix.name = "ESG Default Matrix"
                    }
                }
                else
                {
                    ctx.accountWeightMatrices = matrices;
                }
            });

            //return ctx.$q.defer().promise
            return promise;
        }


        public getScheduledWeightMatricesByAccountId(accountId: string): ng.IPromise<WeightMatrix[]> {
            var ctx = this;
            var promise = ctx.WeightMatricesService.listScheduledWeightMatricesByAccountId(accountId);
            promise.then((matrices: WeightMatrix[]) => {
                ctx.accountScheduledWeightMatrices = matrices;
            });
            return promise;
        }

        private getMatricesSlotsPerPlatform(): ng.IPromise<number> 
        {
            var ctx = this;
            var promise = ctx.WeightMatricesService.getMatricesSlotsPerPlatform();
            promise.then((count: number) => {
                ctx.totalSlots = count;
            });

            return promise;
        }

        private getAccountSelectOptions() {
            var ctx = this;

            var listOptions = new CommonAdmin.HttpGetOptionsDto();

            listOptions.skip = 0;
            listOptions.take = 5000;
            listOptions.orderBy = ['name'];
            listOptions.orderAscending = true;

            var promise = ctx.AccountsService.accountsGetList(listOptions, 'Active', '', false);

            promise.then(data => {
                ctx.accountsList = data;
            });

            return promise;
        }


        public onSelectExcel($files): any {
            var ctx = this;
            ctx.selectedFile = null;
            var file = $files[0]; // html assures is just 1
            if (file && (file.type != "application/vnd.ms-excel" && file.type != "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) {
                ctx.notificationFactory.error("", "Please upload an excel file.");
            }
            else if (file) {
                ctx.selectedFile = file;
            }

            if (!ctx.selectedFile) {
                this.weightMatrixUploadErrors = null;
            }
        }

        public loadAccountCustomMatrices() {
            var ctx = this;
            
            var selectedAccounts = ctx.accountsList.filter(function (el) {
                return el.id == ctx.accountId;
            });

            if (selectedAccounts.length == 1) {
                ctx.selectedAccount = selectedAccounts[0];
            }

            var wmPromise = ctx.getWeightMatricesByAccountId(ctx.selectedAccount.id);
            var schWmPromise = ctx.getScheduledWeightMatricesByAccountId(ctx.selectedAccount.id);

            ctx.$q.all([wmPromise, schWmPromise])
                .then(function () {

                var findNewAccountScheduledWeightMatrices = ctx.accountScheduledWeightMatrices.filter(function (el) {
                    var foundInWM = ctx.accountWeightMatrices.filter(function (element) {
                        return element.name == el.name;
                    });
                    return foundInWM.length == 0;
                });

                //we don't need to include the edited weight matrices from scheduled weight matrices, only the new ones
                ctx.accountScheduledWeightMatrices = findNewAccountScheduledWeightMatrices;
                
            })
            ['catch'](function () {
                ctx.notificationFactory.error('', 'There was an error loading the account weight matrices');
            });

        }

        public uploadWeightMatrix() {

            var ctx = this;
            var fileDefined = false;

            var files = $('#weightMatrixFile').get(0)['files'];
            if (files != undefined && files.length > 0)
                fileDefined = true;

            if (files == undefined && $('#weightMatrixFile').val() != undefined && $('#weightMatrixFile').val() != "")
            {
                fileDefined = true;
                files = [$('#weightMatrixFile').val()];
            }

            if (!fileDefined)
            {
                ctx.notificationFactory.error("", "no weight matrix selected");
                ctx.$rootScope['loading'] = false;
                return;
            }
            //ctx.defaultWeightMatrix.isFocusedRatings = ctx.isFR;

            var promise = ctx.doWeightMatrixTaskUpload(ctx.defaultWeightMatrix, files);
            promise.finally(() => {
                ctx.$rootScope['loading'] = false;
            });
            
        }

        private doWeightMatrixTaskUpload(uploadDto: WeightMatrix, files: any[]): ng.IPromise<string> {
            var ctx = this;
            ctx.$rootScope['loading'] = true;

            //var now = new Date();
            //var now_utc = new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds());
            
            var taskTitle = "Upload " + uploadDto.name + " weight matrix";

            var promise = ctx.LongRunningTaskManagerService.runTaskWithUpload(
                taskTitle, // title
                JSON.stringify(uploadDto), // paramJson
                Sustainalytics.LRTM.LongRunningTaskTypeEnum.WeightMatrixUpload, // taskType
                files, // files
                null, // uploadProgressFunc
                true, // isDownload
                (id, newStatus, oldStatus, taskInstance) => ctx.statusChangedCallback(id, newStatus, oldStatus, taskInstance) // statusChangedCallback
                );
            return promise;
        }

        private statusChangedCallback(taskInstanceId: string, newStatus: LRTM.LongRunningTaskInstanceStatusEnum, oldStatus: LRTM.LongRunningTaskInstanceStatusEnum, taskInstance: LRTM.LongRunningTaskInstance): void {
            var ctx = this;

            if (newStatus === LRTM.LongRunningTaskInstanceStatusEnum.Failed) {
                var promise = ctx.LongRunningTaskManagerService.getResult(taskInstanceId, false);
                promise.then(function (res) {
                    ctx.$rootScope['loading'] = false;
                    var serverErrors = taskInstance.status.taskStatus.errors;
                    if (serverErrors && serverErrors.length > 0) {

                        //serverErrors.forEach(serverErr => {
                        //    taskInstance.errors.push(serverErr.arguments[0]);
                        //});
                        //ctx.weightMatrixUploadErrors = taskInstance.errors[0];

                        ctx.weightMatrixUploadErrors = serverErrors[0].arguments[0];
                    }
                });
            }

            // display result
            if (newStatus == LRTM.LongRunningTaskInstanceStatusEnum.Finished) {
                var promise = ctx.LongRunningTaskManagerService.getResult(taskInstanceId, false);
                promise.then(function (res) {

                    console.log(taskInstance);

                    if (taskInstance.status.taskStatus.details && taskInstance.status.taskStatus.details.length > 0) {
                        ctx.$rootScope['loading'] = false;
                        //ctx.cancel(newStatus);
                    }
                });
            }
        }

        public cancel = function (newStatus)
        {
            var ctx = this;
            ctx.$rootScope['loading'] = false;
        };


        public addCustomWeightMatrix() {
            var ctx = this;

            if (!ctx.accountId) {
                ctx.notificationFactory.error("", "Please select an account first!");
                return;
            }

            if (ctx.selectedAccount.platformTier == AdminAccounts.AccessLevel.Tier3) {
                ctx.notificationFactory.error("", "A Tier 3 Type customer cannot upload custom matrices!");
                return;
            }

            //validate count threshold
            //max 100 matrices per platform
            if (ctx.totalSlots + 1 >= 100) {
                ctx.notificationFactory.error("", "We do not support more than 100 matrices on GAP !");
                return;
            }

            //Tier 1 max 5
            if (ctx.selectedAccount.platformTier == AdminAccounts.AccessLevel.Tier1
                && (ctx.accountScheduledWeightMatrices.length + ctx.accountWeightMatrices.length) >= 5)
            {
                ctx.notificationFactory.error("", "Selected account cannot have more than 5 custom weight matrices !");
                return;
            }

            //Tier 2 max 2
            if (ctx.selectedAccount.platformTier == AdminAccounts.AccessLevel.Tier2
                && (ctx.accountScheduledWeightMatrices.length + ctx.accountWeightMatrices.length) >= 2) {
                ctx.notificationFactory.error("", "Selected account cannot have more than 2 custom weight matrices !");
                return;
            }
            
            var modalInstance = ctx.$modal.open(
                {
                    templateUrl: 'Views/ESGRatings/WeightMatrixAddEdit.html',
                    controller: 'WeightMatrixAddEditController',
                    size: 'lg',
                    backdrop: 'static',
                    resolve:
                    {
                        accountWeightMatrices: function () {
                            return ctx.accountWeightMatrices;
                        },
                        accountScheduledWeightMatrices: function () {
                            return ctx.accountScheduledWeightMatrices;
                        },
                        totalSlots: function () {
                            return ctx.totalSlots;
                        },
                        selectedAccount: function () {
                            return ctx.selectedAccount;
                        },
                        editedWeightMatrix: function () {
                            var newWM = new WeightMatrix();
                            newWM.accountId = ctx.selectedAccount.id;
                            newWM.name = "";
                            return newWM;
                        }
                    }
                });

            modalInstance.result.then((out) => {
                if (out['reload'])
                {
                    ctx.loadAccountCustomMatrices();
                }
                if (out['err']) {
                    ctx.weightMatrixUploadErrors = out['err'];
                }

            });
        }


        public editCustomWeightMatrix(matrix: WeightMatrix) {
            var ctx = this;
            
            var modalInstance = ctx.$modal.open(
                {
                    templateUrl: 'Views/ESGRatings/WeightMatrixAddEdit.html',
                    controller: 'WeightMatrixAddEditController',
                    size: 'lg',
                    backdrop: 'static',
                    resolve:
                    {
                        accountWeightMatrices: function () {
                            return ctx.accountWeightMatrices;
                        },
                        accountScheduledWeightMatrices: function () {
                            return ctx.accountScheduledWeightMatrices;
                        },
                        totalSlots: function () {
                            return ctx.totalSlots;
                        },
                        selectedAccount: function () {
                            return ctx.selectedAccount;
                        },
                        editedWeightMatrix: function () {

                            var wm = new WeightMatrix();
                            wm.id = matrix.id;
                            wm.accountId = matrix.accountId;
                            wm.name = matrix.name;
                            return wm;
                        }
                    }
                });

            modalInstance.result.then((out) => {
                if (out['reload']) {
                    ctx.loadAccountCustomMatrices();
                }
                if (out['err']) {
                    ctx.weightMatrixUploadErrors = out['err'];
                }
            });
        
        }


        public deleteCustomWeightMatrix(matrix: WeightMatrix) {
            var ctx = this;

            if (matrix.isSelectedInActiveProfile) {
                ctx.notificationFactory.error("", "You cannot mark for removal a matrix selected in the account's active ESG profile !");
                return;
            }

            var modalInstanceDelete = ctx.$modal.open({
                templateUrl: 'Views/ESGRatings/WeightMatrixDeleteConfirmation.html',
                controller: 'WeightMatrixDeleteConfirmationController',
                size: 'lg',
                backdrop: 'static'
            });

            modalInstanceDelete.result.then((out) => {
                if (out)
                {
                    var promise = ctx.WeightMatricesService.deleteCustomWeightMatrix(matrix.id);
                    promise.then((data) => {
                        ctx.getWeightMatricesByAccountId(matrix.accountId);
                    });
                }
            });
        }

        public downloadCustomWeightMatrix(matrix: WeightMatrix) {
            var ctx = this;
            ctx.LongRunningTaskManagerService.runTask(matrix.name + " " + moment().format("YYYY-MM-DD_HH-mm-ss-SSS"), JSON.stringify({ weightMatrixId: matrix.id }), LRTM.LongRunningTaskTypeEnum.WeightMatrixDownload, true, null);
        }

        public downloadDefaultWeightMatrix()
        {
            var ctx = this;
            ctx.LongRunningTaskManagerService.runTask(ctx.defaultWeightMatrix.name + " " + moment().format("YYYY-MM-DD_HH-mm-ss-SSS"), JSON.stringify({ weightMatrixId: ctx.defaultWeightMatrix.id }), LRTM.LongRunningTaskTypeEnum.WeightMatrixDownload, true, null);
        }
    }


    var mod = angular.module(esgRatingsAdminModuleName);

    mod.controller('WeightMatricesController',
        ['$rootScope', '$scope', '$q', '$location', '$state', '$modal', 'WeightMatricesService', 'LongRunningTaskManagerService', 'notificationFactory', 'AccountsService', WeightMatricesController]);
}